from functools import reduce
from django.shortcuts import render
from rest_framework.generics import ListAPIView
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
import redis
from .models import Carousel,Category,Goods,GoodCollect
from .serializers import CarouselSer,GoodsSer,CateSer,GoodImgSer,GoodCollectSer
from users.models import User
from rest_framework_jwt.utils import jwt_decode_handler



#伦播图
# class CarouselView(ListAPIView):
#     queryset = Carousel.objects.all()
#     serializer_class = CarouselSer
#伦播图
class CarouselView(APIView):
    def get(self, request):
        # 获取所有的轮播图
        cars = Carousel.objects.all()
        ser = CarouselSer(cars, many=True)
        return Response(ser.data)




# 商品类别
class GoodsByCateName(APIView):
    def post(self, request):
        # 根据类别名获取商品数据
        # 1. 获取前端传来的类别名字
        # 2. post 请求, 可以直接获取
        # 3. 根据类别查询商品
        name = request.data.get('categoryName')
        # 获取类别信息
        cate = Category.objects.get(cate_name=name)
        # 根据类别获取商品
        goods = cate.goods_set.all()
        # 使用序列化器输出
        good_ser = GoodsSer(goods, many=True)
        return Response(good_ser.data)










# 热门商品
class HotProductViews(APIView):
    def post(self, request):
        # 1. 获取前端传递来的参数:["电视机", "空调", "洗衣机"],
        # 2. 前端传来的是列表, 列表中是商品类别[]
        # 3.根据商品类别获取商品,每个商品类别下的商品都要获取, []
        # 4.根据商品里的销量进行排序, 销量越高,越热门
        # 前端传来的类别信息
        cate_names = request.data.get('categoryName')
        # 根据类别名获取商品类别
        # cates 存放的商品类别
        # cates = []
        # for name in cate_names:
        #     cates.append(Category.objects.get(cate_name=name))
        # 试用版列表推导式改写代码
        cates = [Category.objects.get(cate_name=name) for name in cate_names ]
        # 根据商品类别获取商品
        # goods 存放的是每个类别下的商品
        # goods = []
        # for cate in cates:
        #     goods.append(cate.goods_set.all())

        goods = [cate.goods_set.all() for cate in cates]

        # 根据商品销量对商品进行排序
        # map 和reduce 都是把可迭代对象的元素放在func中进行操作,但是返回的结果不一样
        # reduce:(func, iterable)---> 返回的是值
        # map:(func, iterable) ---> 返回的是新的迭代对象[]
        # reduce(lambda x,y: x | y, goods) 会拿到所有商品放在一起的一个列表
        # order_by()默认是升序排列, 我们要降序排列,前面加-
        res = reduce(lambda x, y: x | y, goods).order_by('-count')
        # 对返回的结果进行序列化输出
        ser = GoodsSer(res, many=True)
        return Response(ser.data)



# 获取所有的商品类别
class CategoryView(APIView):
    def post(self, request):
        cates = Category.objects.all()
        ser = CateSer(cates, many=True)
        return Response(ser.data)



# 根据类别id获取此类别下所有的商品
class GoodsByCategoryId(APIView):
    def get(self, request):
        # 根据前端传来的类别id获取商品
        # 1. 获取到前端传递来的商品类别
        # cate_id = request.data.get('categoryID')[0]
        # TODO 查询字符串传参
        cate_id = request.query_params['categoryID']
        print("cate_id>>>", cate_id)
        print("cate_id>>>", type(cate_id))
        try:
            cate = Category.objects.get(id=cate_id)
        except Exception  as e:
            return Response({'msg':"没有此类别"})
        # 根据类别获取所有的商品
        goods = cate.goods_set.all()
        good_ser = GoodsSer(goods, many=True)
        return Response(good_ser.data)


class MyPagenations(PageNumberPagination):
    # 分页时前端查询的关键字
    page_size_query_param = "pageSize"
    page_query_param = "page"
    page_size = 7





# 获取所有的商品
 # 分页器
    # 指定分页器:
    # 有2种配置方式:
    # 1. 在settings的全局配置
    # 2. 在指定类视图下配置,只对当前的类视图分页
class GoodsViews(ListAPIView):
    queryset = Goods.objects.all()
    serializer_class = GoodsSer
    pagination_class = MyPagenations











# 商品详情
# 商品图片
# 1.获取商品id
# 2.判断商品id
# 3.获取图片
# 4.返回前端后展示商品图片
class  GoodPicture(APIView):
    def get(self,request):
        #根据商品id获取商品然后再根据商品获取商品图片
        gid=request.query_params.get('gid')
        if gid:
            try:
                good=Goods.objects.get(id=gid)
            except Exception as e:
                return Response({"msg":"没有此商品","code":400})
            # 根据商品获取商品图片
            imgs=good.goodimg_set.all()
            # 对商品图片进行序列化输出
            ser=GoodImgSer(imgs,many=True)
            return Response(ser.data)
        else:
            return Response({'msg': "商品id 获取错误", "code": 400})



# 商品详情
class GoodDetail(APIView):
    def get(self, request):
        # 获取商品id: 查询字符串传参, query_params
        gid = request.query_params.get('gid')
        if gid:
            # 根据商品id 获取商品,然后再根据商品获取商品图片
            try:
                good = Goods.objects.get(id=gid)
            except Exception as e:
                return Response({"msg": "没有此商品", "code": 400})
            ser = GoodsSer(good)
            return Response(ser.data)
        else:
            # gid 获取失败
            return Response({'msg': "商品id 获取错误", "code": 400})












# 添加历史浏览记录
# 前端传递的参数是:gid, token
# 后端:
# 1. 获取前端传来的gid 和 token
# 2. 判断gid的商品是否存在
# 3. 判断token, 判断用户是否登录, 没有的话就登录
# 4. 判断没问题的把用户信息和商品信息写入redis,list : key(user.id)/v(商品)
# 5. 添加完成,返回
class AddHistory(APIView):
    def post(self,request):
        # 获取前端传来的gid 和 token
        gid = request.data.get('productID')
        token = request.data.get('token')
        print("token>>", token)
        # 判断
        if not token:
            # 此时没有token,shuoming 没有登录
            return Response({'msg':"请先登录!","code":400})
        else:
            # 登录过的,需要校验token
            # decode:解码,
            payload = jwt_decode_handler(token)
            # 在payload 中获取登录的用户信息
            print("payload>>>", payload)
            user_id = payload.get('user_id')
            # 把用户信息和商品id写入redis
            redis_cli = redis.Redis()
            # 写入redis: list   history_userid: gid
            history = "history_%s"%user_id
            # 直接添加
            # 若存在此商品直接删除
            redis_cli.lrem(history,0, gid)
            # 删除后载添加
            redis_cli.lpush(history,gid)
            redis_cli.close()

            return Response({'msg':"添加历史浏览记录成功","code":200})











# 添加收藏
# 思路分析:
# 1. 获取前端传来的用户以及商品id
# 2. 写入数据库: goodscollect
# 3. 添加收藏,必须先登录
class CollectViews(APIView):
    def post(self,request):
        dict_user = request.data.get('user')
        print("user>>>>",dict_user)
        gid = request.data.get('product_id')
        # 判断商品是否存在
        if not dict_user:
            return Response({'msg':"获取用户信息错误","code":400})
        if not gid:
            return Response({"msg":"商品错误","code": 400})
        try:
            user = User.objects.get(username=dict_user['userName'])
        except Exception as e:
            return Response({'msg':"没有此用户","code":400})
        try:
            good = Goods.objects.get(id=gid)
        except Exception as e:
            return Response({'msg':"没有此商品","code":400})
        # 有商品和用户,写入户数据库
        good = GoodCollect.objects.create(user=user, goods=good)
        ser = GoodCollectSer(good)
        return Response({"code":200,"data":ser.data,"msg":"添加收藏成功"})






















